;
;		FILES.A86
;
;Disk file routines for MODEM9.xx.
;
;
;Multi-file access subroutine.  Allows processing of multiple files
;(i.e., *.ASM) from disk.  This routine builds the proper name in the
;FCB each time it is called.  This command would be used in such pro-
;grams such as modem transfer, tape save, etc. in which you want to
;process single or multiple files.
;
;The FCB will be set up with the next name, ready to do normal proces-
;sing (OPEN, READ, etc.) when routine is called.
;
;Carry is set if no more names can be found
;
MFNAME:				;INIT DMA ADDR, FCB
	MOV	CL,STDMA
	MOV	DX,OFFSET 80H
	INT	224
	MOV	byte ptr .FCBEXT,0
	TEST	MFFLG1,0FFH
	JNZ	MFN01		;IF FIRST TIME
	MOV	MFFLG1,1	;TURN OFF 1ST TIME SW
	MOV	BX,OFFSET FCB	;SAVE THE REQUESTED NAME
	MOV	DX,OFFSET MFREQ
	MOV	CX,OFFSET 12
	CALL	MOVER
	MOV	AL,BYTE PTR .FCB
	MOV	MFCUR,AL	;SAVE DISK IN CURRENT FCB
	MOV	BX,OFFSET MFREQ	;SRCHF REQ NAME
	MOV	DX,OFFSET FCB
	MOV	CX,OFFSET 12
	CALL	MOVER
	PUSH	CX
	PUSH	DX
	PUSH	BX
	MOV	CL,SRCHF
	MOV	DX,OFFSET FCB
	INT	224
	POP	BX
	POP	DX
	POP	CX
	JMP	MFN02
;
MFN01:
	MOV	BX,OFFSET MFCUR	;SRCHF CURR NAME
	MOV	DX,OFFSET FCB
	MOV	CX,OFFSET 12
	CALL	MOVER
	MOV	CL,SRCHF
	MOV	DX,OFFSET FCB
	INT	224
	MOV	BX,OFFSET MFREQ	;SRCHN REQ NAME
	MOV	DX,OFFSET FCB
	MOV	CX,OFFSET 12
	CALL	MOVER
	MOV	CL,SRCHN
	MOV	DX,OFFSET FCB
	INT	224
MFN02:
	INC	AL		;RETURN CARRY IF NOT FOUND
	STC
	JNZ	MFFIX1
	MOV	MFFLG1,AL
	RET
;
MFFIX1:
	DEC	AL		;MOVE NAME FOUND TO CURR
	AND	AL,3
	ADD	AL,AL
	ADD	AL,AL
	ADD	AL,AL
	ADD	AL,AL
	ADD	AL,AL
	ADD	AL,81H
	MOV	BL,AL
	MOV	BH,0
	PUSH	BX		;SAVE NAME POINTER
	MOV	DX,OFFSET MFCUR+1
	MOV	CX,OFFSET 11
	CALL	MOVER
	POP	BX		;MOVE NAME FOUND TO FCB
	MOV	DX,OFFSET FCB+1
	MOV	CX,OFFSET 11
	CALL	MOVER
	XOR	AL,AL		;SETUP FCB
	MOV	BYTE PTR .FCBEXT,AL
	MOV	BYTE PTR .FCBRNO,AL
	RET
;
; Move subroutine
;
MOVER:	MOV	AL,BYTE PTR [BX]
	XCHG	BX,DX
	MOV	BYTE PTR [BX],AL
	XCHG	BX,DX
	INC	BX
	INC	DX
	DEC	CX
	JNZ	MOVER
	RET
;
;Lists directory and gives free space remaining on the requested drive.
;
DIRLST:
	MOV	DX,OFFSET CMDBUF	;PUT COMMAND LINE IN FCB
	MOV	BX,OFFSET 5CH
	CALL	CPMLINE
	MOV	BX,OFFSET SRCHFCB
	CALL	INITFCBS
	MOV	AL,BYTE PTR .6CH	;GET DRIVE #
	MOV	SRCHFCB,AL
	MOV	AL,BYTE PTR .6DH
	CMP	AL,20H		;IF BLANK GET ALL NAMES
	PUSH	AX
	JNZ	DIRLST1
	CALL	QSTMARK
DIRLST1:
	POP	AX
	JZ	DIRLST2
	CALL	MOVENAME	;ELSE MOVE NAME INTO FCB
DIRLST2:
	MOV	DX,OFFSET 80H
	MOV	CL,STDMA
	INT	224
	MOV	NAMEGD,0
	MOV	AL,NOOFCOL	;GET NUMBER OF COLUMNS
	MOV	NAMECT,AL	;STORE TO CALCULATE CRLF POSITION
	MOV	DX,OFFSET SRCHFCB
	MOV	CL,SRCHF	;DO FIRST SEARCH
	INT	224
	CMP	AL,0FFH
	JZ	NOFILE
	PUSH	AX
DIRLP:
	POP	AX
	CALL	GETADD
	ADD	BX,15		;OFFSET FOR RECORD COUNT
	MOV	AL,BYTE PTR [BX]
	OR	AL,AL
	JZ	NEXTSR		;NO LIST IF FILE IS ZERO LENGTH
	ADD	BX,-5		;POINT TO $SYS ATTRIB BYTE
	MOV	AL,BYTE PTR [BX]
	AND	AL,80H
	JNZ	NEXTSR		;NO LIST IF $SYS FILE
	ADD	BX,-10		;POINT TO BEGINNING OF NAME
	INC	BX		;POINT TO FIRST LETTER
	MOV	DX,OFFSET PRNTNAME
	MOV	CH,8
	CALL	MOVE
	INC	DX
	MOV	CH,3
	CALL	MOVE
	CALL	ILPRT
PRNTNAME:
	DB '        ','.','   ',' ', 0   ;8 SPACES, PERIOD, 3 SPACES, 1 SPACE
	MOV	NAMEGD,0FFH
NEXTSR:
	MOV	DX,OFFSET SRCHFCB
	MOV	CL,SRCHN	;DO NEXT SEARCH
	INT	224
	CMP	AL,0FFH
	JZ	DIRDONE
	PUSH	AX
	TEST	NAMEGD,0FFH
	JZ	DIRLP
	DEC	NAMECT
	JNZ	NEXTSR1
	CALL	NEWCT
	JMPS	NEXTSR2
NEXTSR1:
	CALL	FENCE
NEXTSR2:
	MOV	NAMEGD,0
	JMP	DIRLP
;
NOFILE:
	CALL	ILPRT
	DB	'NO FILE',0
;
; Determines free space remaining
;
DIRDONE:
	MOV	AL,SRCHFCB
	OR	AL,AL
	JZ	DEFLT
	DEC	AL
	MOV	DL,AL
	MOV	CL,SELDSK
	INT	224
DEFLT:
	MOV	CL,GETPARM 	;CURRENT DISK PARAMETER BLOACK
	INT	224
	ADD	BX,2
	MOV	AL,ES: BYTE PTR [BX]		;GET BLOCK SHIFT FACTOR
	MOV	BSHIFTF,AL
	INC	BX		;BUMP TO BLOCK MASK
	MOV	AL,ES: BYTE PTR [BX]		;GET IT
	MOV	BMASK,AL
	ADD	BX,2
	MOV	DX,ES: WORD PTR [BX] ; GET MAX BLOCK NUMBER
;	MOV	DL,ES: BYTE PTR [BX] ;GET MAX BLOCK NUMBER
;	INC	BX
;	MOV	DH,ES: BYTE PTR [BX]
;	XCHG	BX,DX
	MOV	BMAX,DX		;PUT IT AWAY
	MOV	CL,GETALC 	;ADDRESS OF CP/M ALLOCATION VECTOR
	INT	224
	XCHG	BX,DX		;GET ITS LENGTH
	MOV	BX,BMAX
	INC	BX
	MOV	CX,0		;INITIALIZE BLOCK COUNT TO ZERO
GSPBYT:
	PUSH	DX		;SAVE ALLOCATION ADDRESS
	XCHG	BX,DX
	MOV	AL,ES: BYTE PTR [BX]
	XCHG	BX,DX
	MOV	DL,8		;SET TO PROCESS 8 BLOCKS
GSPLUP:
	RCL	AL,1		;TEST BIT
	JC	NOTFRE
	INC	CX
NOTFRE:
	MOV	DH,AL		;SAVE BITS
	DEC	BX
	MOV	AL,BL
	OR	AL,BH
	JZ	ENDALC		;QUIT IF OUT OF BLOCKS
	MOV	AL,DH		;RESTORE BITS
	DEC	DL		;COUNT DOWN 8 BITS
	JNZ	GSPLUP		;DO ANOTHER BIT
	POP	DX		;BUMP TO NEXT COUNT OF ALLOCATION VECTOR
	INC	DX
	JMP	GSPBYT		;PROCESS IT
;
ENDALC:
	POP	DX		;CLEAR ALLOCATION VECTOR FROM STACK
	MOV	BX,CX		; COPY TO BX
	MOV	AL,BSHIFTF	;GET BLOCK SHIFT FACTOR
	SUB	AL,3		;CONVERT FROM RECORDS TO THOUSANDS
	JZ	PRTFREE		;SKIP SHIFTS IF 1K BLOCKS
FREKLP:
	ADD	BX,BX		;MULTIPLY BLOCKS BY 'K PER BLOCK'
	DEC	AL
	JNZ	FREKLP
PRTFREE:
	PUSH	BX
	CALL	ILPRT
	DB	CR,LF,'Drive ',0
	MOV	AL,SRCHFCB	;IF NO DRIVE, GET
	OR	AL,AL		;LOGGED IN DRIVE
	JNZ	PRNTHD
	MOV	CL,CURDSK
	INT	224
	INC	AL
PRNTHD:
	ADD	AL,'A'-1
	MOV	DRNAME,AL
	CALL	ILPRT
DRNAME	DB	'  has ',0
	POP	BX		;GET NUMBER OF BYTES AVAILABLE
	CALL	DECOUT
	CALL	ILPRT
	DB	'K bytes free',CR,LF,0
	RET
;
; Subroutines
;
FENCE:
	CALL	ILPRT
	DB	'| ',0
	RET
;
NEWCT:
	CALL	CRLF
	MOV	AL,NOOFCOL
	MOV	NAMECT,AL
	RET
;
QSTMARK:
	MOV	AL,'?'		;IF BLANK IN FCB, PUT IN 11 ?'s
	MOV	CH,11
	MOV	BX,OFFSET SRCHFCB+1
QSTLP:
	MOV	BYTE PTR [BX],AL
	INC	BX
	DEC	CH
	JNZ	QSTLP
	RET
;
MOVENAME:
	MOV	BX,OFFSET 6DH
	MOV	DX,OFFSET SRCHFCB+1
	MOV	CH,11
	CALL	MOVE		;MOVE IN MAIN PROGRAM
	RET
;
GETADD:
	AND	AL,03H		;GET MOD4 FOR CP/M 1.4
	ADD	AL,AL		;ADD 32
	ADD	AL,AL
	ADD	AL,AL
	ADD	AL,AL
	ADD	AL,AL
	MOV	DL,AL
	MOV	DH,0
	MOV	BX,OFFSET 80H	;ADD DMA OFFSET
	ADD	BX,DX
	RET
;
;IN CP/M V.2, IF FILE IS R/O OR SYS, IT IS CHANGED TO 'BAK'.
;
CKCPM2:
	MOV	CL,STDMA
	MOV	DX,OFFSET 80H
	INT	224
	MOV	CL,SRCHF	;SEARCH FOR FILE
	MOV	DX,OFFSET FCB
	INT	224
	CMP	AL,0FFH
	JNZ	CKCPM2A
	RET
CKCPM2A:
	ADD	AL,AL
	ADD	AL,AL		;MULT A-REG BY..
	ADD	AL,AL
	ADD	AL,AL		;..32 TO FIND..
	ADD	AL,AL		;..NAME IN DMA.
	MOV	BX,OFFSET 80H
	ADD	AL,BL
	MOV	BL,AL		;HL POINTS TO DIR NAME
	MOV	DX,OFFSET 9
	ADD	BX,DX		;POINT TO R/O ATTRIB BYTE
	MOV	AL,BYTE PTR [BX]
	AND	AL,80H		;TEST MSB
	JNZ	MKCHG		;IF SET, MAKE CHANGE
	INC	BX		;CHECK SYSTEM ATTRIB BYTE
	MOV	AL,BYTE PTR [BX]
	AND	AL,80H
	JNZ	CKCPM2B		; IS $SYS OR $R/O
	RET
CKCPM2B:
	DEC	BX
MKCHG:
	MOV	DX, -8
	ADD	BX,DX		;POINT HL TO FILENAME + 1
	MOV	DX,OFFSET FCB+1	;MOVE DIR NAME TO FCB..
	MOV	CH,11	;..WITHOUT CHANGING DRIVE.
	CALL	MOVE
	MOV	BX,OFFSET FCB+9	;R/O ATTRIB
	AND	BYTE PTR [BX],07FH	; STRIP R/O ATTRIB
	INC	BX
	AND	BYTE PTR [BX],07FH	; STRIP SYS ATTRIB
	MOV	DX,OFFSET FCB
	MOV	CL,30	;SET NEW ATTRIBS IN DIR
	INT	224
;
;MAY BE CALLED BY CKBAKUP BELOW. ITS RETURN DONE HERE
;
PLANCHG:
	MOV	BX,OFFSET FCB	;CHANGE NAME TO TYPE "BAK"
	MOV	DX,OFFSET 6CH
	MOV	CH,9	;MOVE DRIVE AND NAME (NOT TYPE)
	CALL	MOVE
	MOV	BX,OFFSET 75H	;START OF TYPE IN FCB2
	MOV	BYTE PTR [BX],'B'
	INC	BX
	MOV	BYTE PTR [BX],'A'
	INC	BX
	MOV	BYTE PTR [BX],'K'
	MOV	DX,OFFSET 6CH
	MOV	CL,ERASE	;ERASE ANY PREV BACKUPS
	INT	224
	MOV	BX,OFFSET 6CH	;FCB2 DR FIELD SHOULD..
	MOV	BYTE PTR [BX],0	;..0 FOR RENAME.
	MOV	DX,OFFSET FCB
	MOV	CL,23	;RENAME
	INT	224
	RET
;
CKBAKUP:
	MOV	AL,BAKUPBYTE
	OR	AL,AL
	JZ	CKBAKUPR
	MOV	CL,SRCHF
	MOV	DX,OFFSET FCB
	INT	224
	INC	AL
	JZ	CKBAKUPR
	JMP	PLANCHG	;IN "CKCPM2" - RET DONE THERE
CKBAKUPR:
	RET
;
ERASFIL:
	MOV	BX,OFFSET FCB	;CHECK FOR WILD CARDS
	MOV	CH,11
ERASFIL1:
	INC	BX
	MOV	AL,BYTE PTR [BX]
	CMP	AL,'?'		;IS IT A WILD CARD?
	JZ	WILDERR		;GO IF SO
	DEC	CH
	JNZ	ERASFIL1
	MOV	AL,BATCHFLG 	;DON'T ASK FOR ERASE..
	OR	AL,AL		;..IN MULTI-FILE MODE,..
	JZ	NOASK		;..JUST DO IT.
	MOV	DX,OFFSET FCB
	MOV	CL,SRCHF
	INT	224
	INC	AL
	JZ	CKBAKUPR
	CALL	ILPRT
	DB	'File exists -- Type ''Y'' to erase: ',BELL,0
	CALL	KEYIN
	PUSH	AX
	CALL	TIPE
	POP	AX
	CALL	UCASE
	CMP	AL,'Y'
	JZ	ERASEIT
	JMP	MENU

ERASEIT:
	CALL	CRLF
NOASK:
	MOV	DX,OFFSET FCB
	MOV	CL,ERASE
	INT	224
	RET
;
WILDERR:
	POP	BX		;RESTORE STACK
	CALL	ILPRT
	DB	'++ No ambiguous file names allowed ++',CR,LF,BELL,0
	JMP	MENU
;
BLKFILE:
	CALL	ILPRT	;ROUTINE IF NO FILE IS NAMED FOR "SEND" OR "RECEIVE"
	DB	CR,LF,'No file specified',CR,LF,BELL,0
	JMP	MENU

MAKEFIL:
	MOV	DX,OFFSET FCB
	MOV	CL,MAKE
	INT	224
	INC	AL
	JZ	MAKEFIL1
	RET
MAKEFIL1:
	CALL	ERXIT
	DB	'Error - Can''t make file',CR,LF
	DB	'Directory is likely full',CR,LF,'$'
;
CNREC:
	MOV	CL,FILSIZ 	;COMPUTE FILE SIZE FUNCTION IN CP/M 2.x
	MOV	DX,OFFSET FCB	;POINT TO FILE CONTROL BLOCK
	INT	224
	MOV	BX,WORD PTR .FCB+33	;GET RECORD COUNT
	MOV	RCNT,BX	;STORE IT
	MOV	BX, 0	;ZERO HL
	MOV	WORD PTR .FCB+33,BX	;RESET RANDOM RECORD IN FCB
	RET
;
OPENFIL:
	XOR	AL,AL
	MOV	BYTE PTR .FCBEXT,AL
	MOV	DX,OFFSET FCB
	MOV	CL,OPEN
	INT	224
	INC	AL
	JNZ	OPENOK
	CALL	ERXIT
	DB	'Can''t open file$'
OPENOK:
	MOV	AL,QFLG
	OR	AL,AL
	JNZ	OPENOK1
	RET

OPENOK1:
	CALL	SENDTIM		;A LIB MACRO SHOWS TIME TO SEND	
	MOV	BYTE PTR .FCBRNO,0  ; MJM - 9.01.05 FIX BATCH SEND
	MOV	BYTE PTR .FCBEXT,0  ; MJM - 9.01.05 FIX BATCH SEND
	RET
;
CLOSFIL:
	MOV	DX,OFFSET FCB
	MOV	CL,CLOSE
	INT	224
	INC	AL
	JZ	CLOSFIL1
	RET

CLOSFIL1:
	CALL	ERXIT
	DB	'Can''t close file$'
RDSECT:
	DEC	SECINBF
	JS	RDBLOCK
	MOV	BX,SECPTR
	MOV	DX,OFFSET 80H
	CALL	MOVE128
	MOV	SECPTR,BX
	RET
;
RDBLOCK:
	MOV	AL,EOFLG
	CMP	AL,1
	STC
	JNZ	RDBLOCK1
	RET
RDBLOCK1:
	MOV	CL,0
	MOV	DX,OFFSET DBUF
RDSECLP:
	PUSH	CX
	PUSH	DX
	MOV	CL,STDMA
	INT	224
	MOV	DX,OFFSET FCB
	MOV	CL,READ
	INT	224
	POP	DX
	POP	CX
	OR	AL,AL
	JZ	RDSECOK
	DEC	AL
	JZ	REOF
	CALL	ERXIT
	DB	'++ File read error ++$'
RDSECOK:
	MOV	BX,OFFSET 80H
	ADD	BX,DX
	XCHG	BX,DX
	INC	CL
	MOV	AL,CL
	CMP	AL,DBUFSIZ*8 ;BUFFER SIZE IN 128 BYTE SECTORS
	JZ	RDBFULL
	JMP	RDSECLP
;
REOF:	MOV	AL,1
	MOV	EOFLG,AL
	MOV	AL,CL
RDBFULL:
	MOV	SECINBF,AL
	MOV	BX,OFFSET DBUF
	MOV	SECPTR,BX
	MOV	DX,OFFSET 80H
	MOV	CL,STDMA
	INT	224
	JMP	RDSECT
;
WRSECT:
	MOV	BX,SECPTR
	XCHG	BX,DX
	MOV	BX,OFFSET 80H
	CALL	MOVE128
	XCHG	BX,DX
	MOV	SECPTR,BX
	MOV	AL,SECINBF
	INC	AL
	MOV	SECINBF,AL
	CMP	AL,DBUFSIZ*8 	;BUFFER SIZE IN 128 BYTE SECTORS
	JZ	WRBLOCK
	RET
WRBLOCK:
	MOV	AL,SECINBF
	OR	AL,AL
	JNZ	WRBLOCK1
	RET
WRBLOCK1:
	MOV	CL,AL
	MOV	DX,OFFSET DBUF
DKWRLP:
	PUSH	BX
	PUSH	DX
	PUSH	CX
	MOV	CL,STDMA
	INT	224
	MOV	DX,OFFSET FCB
	MOV	CL,WRITE
	INT	224
	POP	CX
	POP	DX
	POP	BX
	OR	AL,AL
	JNZ	WRERR
	MOV	BX,OFFSET 80H
	ADD	BX,DX
	XCHG	BX,DX
	DEC	CL
	JNZ	DKWRLP
	XOR	AL,AL
	MOV	SECINBF,AL
	MOV	BX,OFFSET DBUF
	MOV	SECPTR,BX
	RET
;
WRERR:	MOV	CL,CAN
	CALL	SEND
	CALL	ERXIT
	DB	CR,LF,'Error writing file',CR,LF,'$'
;
